﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using thinger.DataConvertLib;

namespace SerialPortDemo_07
{
    public class ModbusRtuDataHandler : DataHandler
    {
        // 接收数据缓存
        private MemoryStream _tempBuffer = new MemoryStream();

        public void ReceievdHandle(byte[] bytes, ByteBuffer byteBuffer)
        {
            // 将接收到的数据写入缓存
            _tempBuffer.Write(bytes, 0, bytes.Length);

            Debug.WriteLine("-------");
            Debug.WriteLine("mem length:" + _tempBuffer.Length);

            if (_tempBuffer.Length < 5) return;

            byte[] result = FindFunctionCode(_tempBuffer.ToArray());

            byte functionCode = result[1];


            // 整包数据长度
            int responseLength = 0;

            switch (functionCode)
            {
                case 0x03:
                    byte dataLength = result[2];

                    responseLength = dataLength + 5; // 读响应长度

                    break;

                case 0x10:

                    responseLength = 8; // 写响应长度
                    break;
            }

            Debug.WriteLine("length:" + responseLength);

            if (responseLength > _tempBuffer.Length) return;

            Check(responseLength, byteBuffer);
        }

        private void Check(int responseLength, ByteBuffer byteBuffer)
        {
            int needCheckNum = (int)(_tempBuffer.Length - responseLength);

            for (int i = 0; i <= needCheckNum; i++)
            {
                byte[] temp = new byte[responseLength - 2];
                byte[] tempCRC = new byte[2];

                byte[] needCheckTemp;

                Array.Copy(_tempBuffer.ToArray(), i, temp, 0, temp.Length);
                Array.Copy(_tempBuffer.ToArray(), temp.Length + i, tempCRC, 0, 2);

                needCheckTemp = CRC.crc16(temp);

                Debug.WriteLine(StringLib.GetHexStringFromByteArray(temp) + " / " + StringLib.GetHexStringFromByteArray(tempCRC) + " ");
                Debug.WriteLine(StringLib.GetHexStringFromByteArray(needCheckTemp));
                Debug.WriteLine(!(tempCRC[0] == needCheckTemp[responseLength - 2] && tempCRC[1] == needCheckTemp[responseLength - 1]));
                Debug.WriteLine(tempCRC[0] + " " + needCheckTemp[responseLength - 2] + " " + tempCRC[1] + " " + needCheckTemp[responseLength - 1]);

                // 数据长度满足条件，判断校验位
                if ((tempCRC[0] == needCheckTemp[responseLength - 2] && tempCRC[1] == needCheckTemp[responseLength - 1]))
                {
                    byte[] tempBytes = new byte[responseLength];
                    Array.Copy(_tempBuffer.ToArray(), i, tempBytes, 0, responseLength);

                    byteBuffer.pushByteArray(tempBytes);

                }

                _tempBuffer = new MemoryStream();
            }
        }

        private byte[] FindFunctionCode(byte[] bytes)
        {
            byte unitId = bytes[0];
            byte functionCode = bytes[1];

            byte[] temp = new byte[3] { unitId, functionCode, bytes[2] };

            if (functionCode != 0x03 && functionCode != 0x10)
            {
                return FindFunctionCode(bytes);
            }

            return temp;
        }
    }
}
